<?php
// *** Tangra (Application Framework and Tools for PHP)
//  $Id$
//

require_once(TANGRA_MAIN_DIR.'db/db_connection.class.php');

require_once(TANGRA_MAIN_DIR.'exceptions/te_dbc_sql_failed.class.php');
require_once(TANGRA_MAIN_DIR.'exceptions/te_dbc_connect_failed.class.php');
require_once(TANGRA_MAIN_DIR.'exceptions/te_dbc_generate_id_failed.class.php');
require_once(TANGRA_MAIN_DIR.'exceptions/te_sql_injection_attempt.class.php');



class ADODB_DB_Connection extends DB_Connection {

	function __construct($dsn) {
		parent::__construct($dsn);
	}


	public function connect() {
		$old_err_rep = error_reporting(SYSTEM_ERROR_REPORTING_PHP4_LIBS);

		$ret = false;
		if ($this->is_connected()) {
			$ret = true;
		} else {
			$this->conn = NULL;

			$a = ADONewConnection($this->get_dsn());

			if ($a) {
				$this->conn = $a;
				$this->conn->SetFetchMode(ADODB_FETCH_NUM);
				$this->conn->autoCommit = $this->get_autocommit();
				$this->set_connected(true);
				$ret = true;
			} else {
//				printbr(urldecode($this->get_dsn()));
				throw new TE_DBC_Connect_Failed();
			}
		}
		error_reporting($old_err_rep);

		return $ret;
	}


	public function disconnect() {
		if ($this->is_connected()) {
			$this->conn->Close();
			$this->set_connected(false);
		}
	}


	public function start_trans() {
		$old_err_rep = error_reporting(SYSTEM_ERROR_REPORTING_PHP4_LIBS);
		$this->conn->StartTrans();
		error_reporting($old_err_rep);
	}


	public function complete_trans() {
		$old_err_rep = error_reporting(SYSTEM_ERROR_REPORTING_PHP4_LIBS);
		$this->conn->CompleteTrans();
		error_reporting($old_err_rep);
	}


	/**
	 *
	 * @param String $sql SQL statement to be execut3ed
	 * @param boolean $ignore_sql_injection_warning If true this method will not throw exception if the SQL looks like injection attempt.
	 * @return ADODB_DB_Recordset
	 */
	public function execute($sql, $ignore_sql_injection_warning = false) {
		if (!$this->is_like_sql_injection($sql)) {
			if ($this->is_connected()) {
				$old_err_rep = error_reporting(SYSTEM_ERROR_REPORTING_PHP4_LIBS);

				$rs_cache = $this->conn->Execute($sql);
				error_reporting($old_err_rep);

				$tmp_error_msg = $this->conn->ErrorMsg();
				if (!$rs_cache) {
					if ($this->conn->transOff > 0) {
						$this->conn->CompleteTrans();
					}

					throw new TE_DBC_SQL_Failed($sql, $tmp_error_msg);
				}

				$rs = new ADODB_DB_Recordset($rs_cache);
			} else {
				throw new TE_DBC('Database connection is in disconnected state. May be you called $dbc->disconnect() somewhere?');
			}
		} else {
			if (!$ignore_sql_injection_warning) {
				throw new TE_SQL_Injection_Attempt($sql);
			}
		}

		return $rs;
	}


	public function select_limit($sql, $num_rows, $offset) {
		$old_err_rep = error_reporting(SYSTEM_ERROR_REPORTING_PHP4_LIBS);

		$rs_cache = $this->conn->SelectLimit($sql, $num_rows, $offset);
		error_reporting($old_err_rep);

		if (!$rs_cache) {
			throw new TE_DBC_SQL_Failed($sql, $this->conn->ErrorMsg());
		}

		$rs = new ADODB_DB_Recordset($rs_cache);

		return $rs;
	}


	public function query($sql) { //alias of execute()
		return $this->execute($sql);
	}


	public function generate_id($sequence_name, $start = 1) {
		$old_err_rep = error_reporting(SYSTEM_ERROR_REPORTING_PHP4_LIBS);

		$ret = $this->conn->GenID($sequence_name, $start);
		error_reporting($old_err_rep);

		if (!$ret) {
			throw new TE_DBC_Generate_Id_Failed($sequence_name);
		}

		return $ret;
	}


	public function fail_trans() {
		$this->conn->FailTrans();
	}


	public function get_error_msg() {
		$this->conn->ErrorMsg();
	}


	function __destruct() {
		$this->disconnect();

	}
}

